package com.gmall.order.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gmall.common.utils.IdWorker;
import com.gmall.coupon.feign.CouponApiFeignClient;
import com.gmall.model.activity.dto.SkuCoupon;
import com.gmall.model.cart.CartInfo;
import com.gmall.model.enums.OrderStatus;
import com.gmall.model.order.OrderDetail;
import com.gmall.model.order.OrderDetailCoupon;
import com.gmall.model.order.OrderInfo;
import com.gmall.model.user.UserAddress;
import com.gmall.order.config.RabbitMQConfig_Delay;
import com.gmall.order.mapper.OrderDetailCouponMapper;
import com.gmall.order.mapper.OrderDetailMapper;
import com.gmall.order.mapper.OrderInfoMapper;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class OrderService {

    @Autowired
    OrderInfoMapper orderInfoMapper;

    @Autowired
    OrderDetailMapper orderDetailMapper;

    @Autowired
    OrderDetailCouponMapper orderDetailCouponMapper;

    @Autowired
    CouponApiFeignClient couponApiFeignClient;

    @Autowired
    WareHttpClient wareHttpClient;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    RedisTemplate redisTemplate;
    /**
     * CAP CP  强一致性 Seata
     * @param userId
     * @param userAddress
     * @param cartList
     * @param comment
     */
    /*@Transactional(isolation = Isolation.SERIALIZABLE,
            timeout = 3,*//*readOnly = true,*//*
            noRollbackFor = ArrayIndexOutOfBoundsException.class,
            rollbackFor = FileNotFoundException.class)*/
    //事务边界 全局事务
    //@GlobalTransactional
    public OrderInfo saveOrder(Long userId,
                          UserAddress userAddress,
                          List<CartInfo> cartList,
                          String comment ) throws IOException {
        //1.生成订单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setConsignee(userAddress.getConsignee());//收货人
        orderInfo.setConsigneeTel(userAddress.getPhoneNum());//收货人电话
        orderInfo.setDeliveryAddress(userAddress.getUserAddress());//收货地址
        orderInfo.setTotalAmount(caculateTotalAmount(cartList));//总支付金额
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());//未支付
        orderInfo.setUserId(userId);
        orderInfo.setOrderComment(comment);

        orderInfo.setOperateTime(new Date());

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime oneMonthLater = now.plusMonths(1);//1个月后的时间
        //LocalDateTime 转化为Date
        // Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());
        Date expireTime = Date.from(oneMonthLater.atZone(ZoneId.systemDefault()).toInstant());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        Date oneMonthLater1 = calendar.getTime();
        orderInfo.setExpireTime(expireTime);

        orderInfo.setCouponAmount(new BigDecimal("0"));
        orderInfo.setOriginalTotalAmount(new BigDecimal("0"));

        orderInfoMapper.insert(orderInfo);//执行保存订单

        Long orderId = orderInfo.getId();//获取订单ID

        List<OrderDetail> orderDetailList = new ArrayList<>();
        cartList.forEach(cartInfo -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());
            orderDetail.setSkuNum(cartInfo.getSkuNum());

            orderDetailMapper.insert(orderDetail);
            orderDetailList.add(orderDetail);

            Long orderDetailId = orderDetail.getId();

            SkuCoupon checkedCoupon = cartInfo.getCheckedCoupon();//最优优惠卷
            if(checkedCoupon!=null){
                OrderDetailCoupon orderDetailCoupon = new OrderDetailCoupon();
                orderDetailCoupon.setOrderId(orderId);
                orderDetailCoupon.setOrderDetailId(orderDetailId);
                orderDetailCoupon.setSkuId(cartInfo.getSkuId());
                orderDetailCoupon.setCouponId(checkedCoupon.getId());//优惠卷ID
                orderDetailCouponMapper.insert(orderDetailCoupon);
                //修改优惠券的状态（另一个微服务）
                couponApiFeignClient.useCoupon(checkedCoupon.getId(),userId,orderId);
            }
        });
        orderInfo.setOrderDetailList(orderDetailList);
        //锁定库存
        //对于我们自己的微服务，Feign（HTTP+Ribbon负载均衡），第三方系统 HTTP调用
        //Feign 网络调用，打电话
        boolean result = wareHttpClient.lockStockSku(orderInfo);

        if(result){
            //往延时队列发送消息
            rabbitTemplate.convertAndSend(
                    RabbitMQConfig_Delay.Exchange_UnPay_direct,
                    RabbitMQConfig_Delay.UnPay_RoutingKey,
                    orderInfo.getId()
            );
            return orderInfo;
        }else{
            throw new RuntimeException("库存锁定失败");
        }
        //删除购物车中已下单的商品


    }

    private BigDecimal caculateTotalAmount(List<CartInfo> cartInfoList) {
        BigDecimal totalAmount = new BigDecimal("0");
        for(int i=0;i<cartInfoList.size();i++){
            CartInfo cartInfo = cartInfoList.get(i);
            BigDecimal skuPrice = cartInfo.getSkuPrice();
            Integer skuNum = cartInfo.getSkuNum();
            SkuCoupon checkedCoupon = cartInfo.getCheckedCoupon();
            if(checkedCoupon!=null){
                BigDecimal payAmount = checkedCoupon.getPayAmount();
                totalAmount = totalAmount.add(payAmount);
            }else{//无优惠卷可以使用
                totalAmount = totalAmount.add(skuPrice.multiply(new BigDecimal(skuNum)));
            }
        }
        return totalAmount;
    }

    public static void main(String[] args) {
        double a = 0.1;
        double b = 0.3;

        double c = b - a;
        BigDecimal a1 = new BigDecimal("0.1");
        BigDecimal b1 = new BigDecimal("0.3");

        BigDecimal c1 = b1.subtract(a1);
        System.out.println(c);
        System.out.println(c1);
    }

    public Page<OrderInfo> findOrderPage(Long userId, Integer pageNo, Integer pageSize) {
        Page<OrderInfo> page = new Page<>(pageNo,pageSize);
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OrderInfo::getUserId,userId);
        return orderInfoMapper.selectPage(page, queryWrapper);
    }

    public OrderInfo getOrderInfoById(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }


    @Autowired
    IdWorker idWorker;
    private final String REDIS_TRADE_NO_KEY = "RepeatUUID:";
    public String genOrderNoUUID(){
        //String orderTradeNo = String.valueOf(idWorker.nextId());
        String orderTradeNo = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(REDIS_TRADE_NO_KEY+orderTradeNo,
                orderTradeNo+"",15, TimeUnit.MINUTES);
        return orderTradeNo;
    }

    public boolean hasOrderNoUUID(String orderTradeNo){
        return redisTemplate.hasKey(REDIS_TRADE_NO_KEY + orderTradeNo);
    }
    public void removeOrderNoUUID(String orderTradeNo){
        redisTemplate.delete(REDIS_TRADE_NO_KEY + orderTradeNo);
    }

}
